class

기본적으로 내장된 클래스class를 우린 자료형datatype이라 부른다.

이러한 자료형을 우리가 독자적으로 정의하면 클래스라 불린다.
예컨대 int는 클래스 내부에 '+'라는 연산에 대해 어떻게 동작할 지가 일일히 정의되어 있는 것이라고 생각할 수 있다.

자료형이 갖는 특성에 대한 정의는 모두 클래스로 할 수 있는 것들이다. 즉, int라는 자료형이 정의되어 있지 않아도 우린 int를 만들어 낼 수 있을 것이다(물론 완벽히 똑같이 만들 수는 없다. 다만 기능을 어느정도 흉내내기 정도는 할 수 있다). 어떻게 할 수 있을까?

class 정의

우선 클래스를 정의하는 것부터 시작하자.
클래스는 아래와 같이 정의한다.

class 클래스_이름:
	def __init__(self, arg1, ...):  #생성자constructor
		...
	def 메소드_이름1(self, arg1, ...):  #메소드method
		...
	def 메소드_이름2(self, arg1, ...):  #메소드
		...

그런데 init은 뭐고 메소드는 또 뭘까?

method란?

클래스 내부에 함수처럼 정의된 부분을 메소드라고 한다.
실제로 함수가 맞다. 하지만 메소드라 불리는 이유는 해당 클래스에서만 작동하는 함수이기 때문이다. 사용하는 방법도 살짝 다르다. 어떻게 사용하는지는 추후 알아보자.
다만, 메소드 함수의 인수에 이상한게 하나 있다. self가 뭘까?
self란, 자기자신(변수)을 가리키는 인수이다. 이게 필요한 이유에 대해서는 예시에서 설명한다.

초기화 메소드: __init__

우리가 어떤 변수를 선언할 때, 반드시 그 변수의 클래스를 결정하고, 초기화하여 사용한다. 이것은 수동으로 초기화할 필요가 없이, 자동으로 초기화되도록 최초 1회만 자동으로 작동하는 메소드라고 생각하면된다.

예시

자, 이제 예시를 통해 구체화해보자.
int를 완전히 구현하는 것은 너무 어렵다. 우린 거기서 덧셈, 그 중에서도 +1 연산만이 가능하도록 정의해볼 것이다.

class MyInt:
    def __init__(self, value):
        self.value = str(value)  
		    # int를 사용하지 않기 위해 str로 저장; 'self.value'라는 이름의 값을 정의.

    def add_one(self):
        # 값이 9가 아닌 경우, 마지막 숫자 하나 증가.
        if self.value[-1] != '9':
            self.value = self.value[:-1] + chr(ord(self.value[-1]) + 1)
        else:
            # 값이 9인 경우, 추가적인 논리가 필요합니다.
            # 여기서는 간단히 처리하기 위해 '10'으로 설정합니다.
            self.value = '10'
        return MyInt(self.value)
        
# 사용 예
a = MyInt(3)  # 초기화 메소드에 의해 a.value = 3 으로 선언됨.
print(a.add_one())  # MyInt(4)

해당 코드 내부에서 int에서 정의된 '+'는 문자열 간의 concatenate 연산과, 다음 순서의 ASCII 코드를 불러오기 위해서만 쓰였다. 더 복잡한 방법이나 원리를 사용하는 것은 보여주고자 하는 의도를 넘어선다. 또한 'a + b'와 같은 방식으로 연산되도록 만들 수도 있지만, 생략한다.

함수와 달리 클래스 내장 함수인 메소드는 인스턴스(클래스로 선언된 변수를 부르는 말)뒤에 '.'을 붙이고 사용한다. 일반적인 함수와 다른건 없다. 예컨대 내가 원하는 함수들을 클래스에 모아놓고, 사용할 수도 있다.

class Math:
    def sqrt(self, num):
        return num ** 0.5

math_instance = Math()
print(math_instance.sqrt(4))  # >>> 2

어떤가? math 모듈을 임포트 해서 사용하는 함수와 완벽히 동일해보인다.
물론, 그래보이기만 할 뿐이다. 실제로 math 모듈의 sqrt함수는 인스턴스 메소드가 아닌 모듈 내의 독립적인 함수이며, 내부적인 작동 방식도 완전히 다르다. (계산 시간 등 차이남.)

다만, 이렇게 쓸 필요가 없다. 이 경우 math_instance에 어떤 값에 대한 상태를 유지하고 저장할 필요가 없기 때문이다. 이것이 메소드와 독립된 함수의 차이라고 할 수 있다.